package com.api.aiyh_kafang.service;

import aiyh.utils.Util;
import aiyh.utils.sqlUtil.sqlResult.impl.BatchSqlResultImpl;
import aiyh.utils.zwl.common.ToolUtil;
import com.api.aiyh_kafang.dao.InvoiceMapping;
import com.api.aiyh_kafang.entity.UfInvoiceConfigDTO;
import com.engine.fna.util.FnaInvoiceUploadUtil;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.weaver.general.TimeUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.h2.util.StringUtils;
import weaver.conn.RecordSet;
import weaver.file.ImageFileManager;
import weaver.fna.invoice.utils.HttpUtil;
import weaver.fna.invoice.utils.ImageUtil;
import weaver.formmode.data.ModeDataIdUpdate;
import weaver.formmode.setup.ModeRightInfo;
import weaver.hrm.User;

import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * @author EBU7-dev1-ayh
 * @create 2021/11/2 0002 15:17
 * 检查发票
 */


public class InvoiceService {

	private final InvoiceMapping invoiceMapping = new InvoiceMapping();
	private final ModeDataIdUpdate mdu = ModeDataIdUpdate.getInstance();
	private final RecordSet rs = new RecordSet();
	private final ToolUtil toolUtil = new ToolUtil();
	private final String ModeTable = "uf_fpyzjb";
	private final String ModeDetailTable = "uf_fpyzjb_dt1";
	private final String ModeDetailTableErr = "uf_fpyzjb_dt3";
	private String formModeId = "17";
	private final String invoiceTable = "fnainvoiceledger";

	public InvoiceService() {
		String formModeId = toolUtil.getSystemParamValue("formModeId");
		if(!StringUtils.isNullOrEmpty(formModeId)){
			this.formModeId = formModeId;
		}
	}

	/**
	 * 查询发票信息，OCR识别
	 *
	 * @param user
	 * @param fileId
	 * @return
	 * @throws IOException
	 */
	public JSONObject getInvoiceInfo(User user, int fileId) throws Exception {
//		方法一
/*		InputStream inputStreamById = ImageFileManager.getInputStreamById(fileId);
		byte[] bytes;
		bytes = IOUtils.toByteArray(inputStreamById);
		JSONObject jsonObject = HttpUtil.postImage(bytes, user);*/

//		方法二
/*		String fileData = FnaInvoiceUploadUtil.changeFileTobase64(fileId);
		byte[] imageBytes = ImageUtil.transformImage(fileData);
		JSONObject jsonObject = HttpUtil.postImage(imageBytes, user);*/


//		方法三
		try {
			InputStream inputStreamById = ImageFileManager.getInputStreamById(fileId);
			BufferedImage imageBuffer = ImageIO.read(inputStreamById);
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			boolean jpeg = ImageIO.write(imageBuffer, "jpeg", byteArrayOutputStream);
			if(!jpeg){
				toolUtil.writeErrorLog("图片转化转化失败！");
			}
			byte[] bytes = byteArrayOutputStream.toByteArray();
			//		toolUtil.writeErrorLog(jsonObject.toString());
			return HttpUtil.postImage(bytes, user);
		}catch (IIOException e){
			InputStream inputStreamById = ImageFileManager.getInputStreamById(fileId);
			BufferedImage imageBuffer = JPEGCodec.createJPEGDecoder(inputStreamById).decodeAsBufferedImage();
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			boolean jpeg = ImageIO.write(imageBuffer, "jpeg", byteArrayOutputStream);
			if(!jpeg){
				toolUtil.writeErrorLog("图片转化转化失败！");
			}
			byte[] bytes = byteArrayOutputStream.toByteArray();
			//		toolUtil.writeErrorLog(jsonObject.toString());
			return HttpUtil.postImage(bytes, user);
		}
	}

	/**
	 * 对比合同信息
	 */
	public Map<String, Object> contrastInvoiceInfo(Map<String, Object> params) {
//		获取到流程表中的明细数据，对比建模表中的发票信息，查验数量是否一致以及发票的钱
//		List<String> fileIdList = (List<String>) params.get("fileIdList");
		String requestId = Util.null2String(params.get("requestId"));
		String workflowId = Util.null2String(params.get("workflowId"));
//		查询建模表数据
		String mainId = invoiceMapping.getMainId(requestId);
		List<Map<String, Object>> modeData = invoiceMapping.selectModeInfo(mainId);
//		查询配置表信息
		UfInvoiceConfigDTO configInfo = invoiceMapping.getConfigInfo(workflowId);
//		查询流程中的发票数据
		List<Map<String, Object>> workflowData = invoiceMapping.selectWorkflowData(workflowId, requestId, configInfo);
//	    对比合同信息，查询出相差的发票
		List<Map<String, Object>> priceNotEqual = new ArrayList<>();
		List<Map<String, Object>> workflowDataRm = new ArrayList<>();
		List<Map<String, Object>> modeDataRm = new ArrayList<>();
		if (configInfo.getInvoiceBrowse() == 1) {
//			属于浏览框
			for (Map<String, Object> workflowDatum : workflowData) {
				String workflowCodeId = Util.null2String(workflowDatum.get(configInfo.getInvoiceField()));
				String workflowCode = "";
				String workflowInvoicePrice = Util.null2String(workflowDatum.get(configInfo.getInvoicePrice()));
				try {
					workflowCode = invoiceMapping.getWorkflowCode(workflowCodeId, invoiceTable);
					workflowDatum.put(configInfo.getInvoiceField(),workflowCode);
					workflowDatum.put("fphm2",workflowCode);
				} catch (Exception e) {
					e.printStackTrace();
					toolUtil.writeErrorLog("发票不存在：" + e);
				}
				for (Map<String, Object> modeDatum : modeData) {
					String modeCode = Util.null2String(modeDatum.get("fphm2"));
					String modePrice = Util.null2String(modeDatum.get("fpje"));
					if (workflowCode.equals(modeCode)) {
//                      发票号码相等，校验发票金额
						if (!workflowInvoicePrice.equals(modePrice)) {
//							金额不相等
//							添加校验失败数据到数组中
							priceNotEqual.add(modeDatum);
						}
//						求差集
						workflowDataRm.add(workflowDatum);
						modeDataRm.add(modeDatum);
						break;
					}
				}
			}
//			求差
//			建模表中多余的发票信息
			modeData.removeAll(modeDataRm);
//			流程中有但是建模表中没有的发票信息
			workflowData.removeAll(workflowDataRm);

		} else {
//			不属于浏览框
			for (Map<String, Object> workflowDatum : workflowData) {
				String workflowCode = Util.null2String(workflowDatum.get(configInfo.getInvoiceField()));
				String workflowInvoicePrice = Util.null2String(workflowDatum.get(configInfo.getInvoicePrice()));
				for (Map<String, Object> modeDatum : modeData) {
					String modeCode = Util.null2String(modeDatum.get("fphm2"));
					String modePrice = Util.null2String(modeDatum.get("fpje"));
					if (workflowCode.equals(modeCode)) {
//                      发票号码相等，校验发票金额
						if (!workflowInvoicePrice.equals(modePrice)) {
//							金额不相等
//							添加校验失败数据到数组中
							priceNotEqual.add(modeDatum);
						}
//						求差集
						workflowDataRm.add(workflowDatum);
						modeDataRm.add(modeDatum);
						break;
					}
				}
			}
//			求差
//			建模表中多余的发票信息
			modeData.removeAll(modeDataRm);
//			流程中有但是建模表中没有的发票信息
			workflowData.removeAll(workflowDataRm);
		}

		List<LinkedHashMap<String, Object>> insertList = new ArrayList<>();
//		将价格不一样的数据保存到建模表明细3中，并标识错误原因为价格不一致
		for (Map<String, Object> map : priceNotEqual) {
			LinkedHashMap<String, Object> data = new LinkedHashMap<>();
			data.put("fphm1", map.get("fphm2"));
			data.put("sbyy","流程发票明细信息表中的发票与扫描识别发票的发票金额不一致！");
			data.put("mainid", mainId);
			insertList.add(data);
		}
//		将建模表多的发票保存到建模表明细3中，并标识错误原因为流程中不存在改发票信息
		for (Map<String, Object> map : modeData) {
			LinkedHashMap<String, Object> data = new LinkedHashMap<>();
			data.put("fphm1", map.get("fphm2"));
			data.put("sbyy", "流程中不存在该发票信息，但扫描发票中存在改发票！");
			data.put("mainid", mainId);
			insertList.add(data);
		}
//		将流程中多的发票保存到建模表明细3中，并标识错误原因为，扫描发票中不存在改发票信息
		for (Map<String, Object> map : workflowData) {
			LinkedHashMap<String, Object> data = new LinkedHashMap<>();
			data.put("fphm1", Util.null2String(map.get(configInfo.getInvoiceField())));
			data.put("sbyy", "流程中存在改发票，但是扫描发票中没有发现该发票信息！");
			data.put("mainid", mainId);
			insertList.add(data);
		}
		RecordSet rs = new RecordSet();
		BatchSqlResultImpl batchSqlResult = Util.createSqlBuilder().insertBatchSql(ModeDetailTableErr, insertList);
		toolUtil.writeErrorLog("SQL：" + batchSqlResult.getSqlStr() + " ---->参数：" + batchSqlResult.getBatchList());
		System.out.println("SQL：" + batchSqlResult.getSqlStr() + " ---->参数：" + batchSqlResult.getBatchList());
/*		for (List list : batchSqlResult.getBatchList()) {
			rs.executeUpdate(batchSqlResult.getSqlStr(),list);
		}*/
		try{
			rs.executeBatchSql(batchSqlResult.getSqlStr(), batchSqlResult.getBatchList());
		}catch(Exception e){
		    e.printStackTrace();
		}
		Map<String, Object> result = new HashMap<>();
		result.put("priceNotEqual", priceNotEqual);
		result.put("workflowData", workflowData);
		result.put("modeData", modeData);
		return result;
	}

	/**
	 * 获取配置信息
	 *
	 * @param workflowId
	 * @return
	 */
	public UfInvoiceConfigDTO getConfigInfo(String workflowId) {
		return invoiceMapping.getConfigInfo(workflowId);
	}

	/**
	 * 保存合同信息
	 *
	 * @param invoiceInfo
	 * @param requestId
	 */
	public void saveInvoiceInfo(JSONObject invoiceInfo, String requestId) {
//		 查询是否已经存在，不存在则新增，存在则更新
		String query = "select * from " + ModeTable + " where lc = ?";
		rs.executeQuery(query, requestId);
		if (rs.next()) {
//			存在，往明细表中添加数据
			saveInvoiceDetail(invoiceInfo, requestId, rs.getString("id"));
			return;
		}
//		添加主表数据，并且添加明细
		int dataId = mdu.getModeDataNewId(ModeTable,
				Util.getIntValue(formModeId, -1),
				1, 0, TimeUtil.getCurrentDateString(),
				TimeUtil.getOnlyCurrentTimeString());
//		 插入数据库信息
		invoiceMapping.saveInvoiceInfo(dataId, ModeTable, requestId);
		saveInvoiceDetail(invoiceInfo, requestId, String.valueOf(dataId));
		ModeRightInfo mri = new ModeRightInfo();
		mri.rebuildModeDataShareByEdit(1, Util.getIntValue(formModeId, -1), dataId);
	}

	/**
	 * 保存发票信息到建模明细表
	 *
	 * @param invoiceInfo
	 * @param requestId
	 * @param mainId
	 */
	public void saveInvoiceDetail(JSONObject invoiceInfo, String requestId, String mainId) {
		String main = mainId;
		if (StringUtils.isNullOrEmpty(main)) {
//		    查询主表数据
			String query = "select * from " + ModeTable + " where lc = ?";
			rs.executeQuery(query, requestId);
			rs.next();
			main = rs.getString("id");
		}
//		保存明细表数据
		JSONObject returnInfo = (JSONObject) invoiceInfo.get("returnInfo");
		toolUtil.writeErrorLog("returnInfo：" + returnInfo);
		if(returnInfo == null){
			throw  new RuntimeException("发票数据获取失败：" + invoiceInfo);
		}
		JSONObject response = (JSONObject) returnInfo.get("response");
		JSONObject data = (JSONObject) response.get("data");
		JSONArray identifyResults = (JSONArray) data.get("identify_results");
		for (int i = 0; i < identifyResults.size(); i++) {
			JSONObject item = (JSONObject) identifyResults.get(i);
			JSONObject details = (JSONObject) item.get("details");
//			查询是否存在该发票，不存在则添加
			if(invoiceMapping.selectExist(main,Util.null2String(details.get("number")))){
				return;
			}
			//		明细表数据
			Map<String, Object> insert = Util.createUtilHashMap()
//				发票号码
					.uPut("fphm2", details.get("number"))
//			    费用日期
					.uPut("fyrq", details.get("date"))
//				服务内容
					.uPut("fwnr", details.get("item_names"))
//				发票金额
					.uPut("fpje", details.get("total"))
					.uPut("mainid", main);
			toolUtil.writeErrorLog("insert：" + insert);
			invoiceMapping.saveInvoiceDetail(insert, ModeDetailTable);
		}
	}
}
